#include "TSkinWindow.h"
#include <QMargins>
#include <QMouseEvent>
#include <QApplication>
#include <QCursor>
#include <QPainter>
#include <QDesktopWidget>
#include <QVBoxLayout>

#include "TMessageBox.h"

TSkinWindow::TSkinWindow(QWidget *parent)
    : TResizableFrame(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint),
      _winState(Qt::WindowNoState),
      _prevWinState(Qt::WindowNoState)
{
    QVBoxLayout* verticalLayout = new QVBoxLayout(this);
    verticalLayout->setContentsMargins(0, 0, 0, 0);
    verticalLayout->setSpacing(0);

    _background = new QFrame(this);
    _background->setObjectName("window_bg");
    verticalLayout->addWidget(_background);

    QVBoxLayout* backgroundLayout = new QVBoxLayout(_background);
    backgroundLayout->setContentsMargins(0, 0, 0, 0);
    backgroundLayout->setSpacing(0);

//    _titlebar = new TTitleBar("window", _background);
//    _titlebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
//    backgroundLayout->addWidget(_titlebar);

//    _closeButton = new QPushButton(_titlebar);
//    _closeButton->setObjectName("close");
//    _closeButton->setToolTip(tr("close"));
//    _titlebar->addWidget(_closeButton);

//    _maximizeButton = new QPushButton(_titlebar);
//    _maximizeButton->setObjectName("maximize");
//    _maximizeButton->setToolTip(tr("maximize"));
//    _titlebar->addWidget(_maximizeButton);

//    _restoreButton = new QPushButton(_titlebar);
//    _restoreButton->setObjectName("restore");
//    _restoreButton->setToolTip(tr("restore"));
//    _titlebar->addWidget(_restoreButton);
//    _restoreButton->hide();

//    _minimizeButton = new QPushButton(_titlebar);
//    _minimizeButton->setObjectName("minimize");
//    _minimizeButton->setToolTip(tr("minimize"));
//    _titlebar->addWidget(_minimizeButton);

    _client = new QWidget(_background);
    _client->setObjectName("window_client");
    _client->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    backgroundLayout->addWidget(_client);

    setResizeEnabled(true);

    connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), this, SLOT(screenWorkAreaResized(int)));
//    connect(_minimizeButton, SIGNAL(clicked()), this, SLOT(minimizeRequested()));
//    connect(_maximizeButton, SIGNAL(clicked()), this, SLOT(maximizeRequested()));
//    connect(_restoreButton, SIGNAL(clicked()), this, SLOT(normalRequested()));
//    connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
//    connect(_titlebar, SIGNAL(moveRequested(const QPoint&, const QPoint&)), this,
//            SLOT(moveRequested(const QPoint&, const QPoint&)));
//    connect(_titlebar, SIGNAL(mouseButtonDblClicked()), this, SLOT(maximizeRequested()));
}

TSkinWindow::~TSkinWindow()
{
    _background = NULL;
    _titlebar = NULL;
//    _minimizeButton = NULL;
//    _maximizeButton = NULL;
//    _restoreButton = NULL;
//    _closeButton = NULL;
    _client = NULL;
}

QRect TSkinWindow::getNormalGeometry() const
{
    if (_winState == Qt::WindowNoState)
        return geometry();
    return _normalGeometry;
}

void TSkinWindow::changeWindowState(Qt::WindowState state)
{
    if (_winState == state)
        return;
    if (state == Qt::WindowNoState) {
        if (_winState == Qt::WindowMinimized) {
            showNormal();
        } else {
            QRect r = QApplication::desktop()->frameGeometry();
            QPoint offset = r.topLeft() - _normalScreenGeometry.topLeft();
            QPoint center = _normalGeometry.center() + offset;
            _normalGeometry.moveCenter(center);
            setGeometry(_normalGeometry);
        }
    } else if (state == Qt::WindowMinimized) {
        showMinimized();
    } else if (state == Qt::WindowMaximized) {
        _normalScreenGeometry = QApplication::desktop()->frameGeometry();
        _normalGeometry = frameGeometry();
        QRect rect = QApplication::desktop()->availableGeometry(this);
        setGeometry(rect);
    }
    _prevWinState = _winState;
    _winState = state;
    windowStateChanged();
}

void TSkinWindow::windowStateChanged()
{
//    if (_winState == Qt::WindowNoState) {
//        _maximizeButton->show();
//        _restoreButton->hide();
//    } else if (_winState == Qt::WindowMaximized) {
//        _restoreButton->show();
//        _maximizeButton->hide();
//    }
}

void TSkinWindow::mousePressEvent(QMouseEvent* e)
{
    if (_winState == Qt::WindowNoState)
        TResizableFrame::mousePressEvent(e);
}

void TSkinWindow::mouseReleaseEvent(QMouseEvent* e)
{
    if (_winState == Qt::WindowNoState)
        TResizableFrame::mouseReleaseEvent(e);
}

void TSkinWindow::changeEvent(QEvent* e)
{
    TResizableFrame::changeEvent(e);
    if (QEvent::WindowStateChange == e->type()) {
        if (_winState == Qt::WindowMinimized) {
            _winState = _prevWinState;
            windowStateChanged();
        }
    } else if (e->type() == QEvent::WindowTitleChange) {
//        _titlebar->setText(windowTitle());
    }
}

void TSkinWindow::showEvent(QShowEvent* e)
{
    QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
    TResizableFrame::showEvent(e);
}

bool TSkinWindow::eventFilter(QObject* obj, QEvent* e)
{
    return ((_winState == Qt::WindowNoState) ? TResizableFrame::eventFilter(obj, e) : false);
}

void TSkinWindow::closeEvent(QCloseEvent* e)
{
    TResizableFrame::closeEvent(e);
    QApplication::instance()->removeEventFilter(this);
    QApplication::restoreOverrideCursor();
}

void TSkinWindow::screenWorkAreaResized(int screen)
{
    if (_winState == Qt::WindowMaximized) {
        int number = QApplication::desktop()->screenNumber(this);
        QRect rect = QApplication::desktop()->availableGeometry(number);
        setGeometry(rect);
    }
}

void TSkinWindow::moveRequested(const QPoint& globalPos, const QPoint& offset)
{
    if (_winState == Qt::WindowMaximized) {
        int nw = _normalGeometry.width();
        int nh = _normalGeometry.height();
        QRect rect = frameGeometry();
        int mw = rect.width();
        QPoint cpos = QCursor::pos();
        float leftPercent = (cpos.x() - rect.left()) / (float) nw;
        float rightPercent = (rect.right() - cpos.x()) / (float) nw;
        if (leftPercent > 0.0f && leftPercent < 0.5f) {
            _normalGeometry.setLeft(rect.left());
        } else if (rightPercent > 0.0f && rightPercent < 0.5f) {
            _normalGeometry.setLeft(rect.right() - nw);
        } else {
            _normalGeometry.setLeft(cpos.x() - ((cpos.x() - rect.left()) * nw) / mw);
        }
        _normalGeometry.setLeft(_normalGeometry.left() + offset.x());
        _normalGeometry.setTop(rect.top() + offset.y());
        _normalGeometry.setWidth(nw);
        _normalGeometry.setHeight(nh);
        changeWindowState(Qt::WindowNoState);
    } else if (_winState == Qt::WindowNoState)
        move(pos() + offset);
}

void TSkinWindow::minimizeRequested()
{
    changeWindowState(Qt::WindowMinimized);
}

void TSkinWindow::normalRequested()
{
    changeWindowState(Qt::WindowNoState);
}

void TSkinWindow::maximizeRequested()
{
    if (((windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || minimumSize() == maximumSize()))
        return;

    if (_winState == Qt::WindowMaximized)
        changeWindowState(Qt::WindowNoState);
    else
        changeWindowState(Qt::WindowMaximized);
}

void TSkinWindow::closeRequested()
{
    TMessageBox dialog(tr("caution"),
                       tr("Are you sure to exit system?"),
                       QMessageBox::Ok | QMessageBox::Cancel,
                       QMessageBox::NoButton, this);
    dialog.centerWindow();
    dialog.exec();
    if (QMessageBox::Ok == dialog.getResult())
        this->close();
}
